package com.xxjh.brs.map.utils;

/**
 * @author CHENCHEN
 * @title a
 * @company 新兴际华科技（天津）有限公司
 * @create 2024-06-11 10:57
 */
public class TileCoordinateConverter {

    /**
     * 根据经度和缩放级别获取图块的X坐标
     * @param lon
     * @param zoom
     * @return
     */
    public static int getOSMTileXFromLongitude(double lon, int zoom) {
        return (int) (Math.floor((lon + 180) / 360 * Math.pow(2, zoom)));
    }

    /**
     * 根据纬度和缩放级别获取图块的Y坐标
     * @param lat
     * @param zoom
     * @return
     */
    public static int getOSMTileYFromLatitude(double lat, int zoom) {
        return (int) (Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom)));
    }

    /**
     * 根据Z、X图块反推经度
     * @param x 图块X坐标
     * @param zoom 缩放级别
     * @return 反推出的经度
     */
    public static double getLongitudeFromOSMTileX(int x, int zoom) {
        return x * 360.0 / Math.pow(2, zoom) - 180.0;
    }

    /**
     * 根据Z、Y图块反推纬度
     * @param y 图块Y坐标
     * @param zoom 缩放级别
     * @return 反推出的纬度
     */
    public static double getLatitudeFromOSMTileY(int y, int zoom) {
        double n = Math.PI - 2 * Math.PI * y / Math.pow(2, zoom);
        return Math.toDegrees(Math.atan(Math.sinh(n)));
    }

    /**
     * 检查瓦片中心点的经纬度是否在给定范围内
     * @param x 图块x坐标
     * @param y 图块Y坐标
     * @param zoom 缩放级别
     * @param extent 经纬度
     * @return 是否
     */
    public static boolean isTileInExtent(int x, int y, int zoom, double[] extent) {
        // 确保数组长度正确
        if (extent.length != 4) {
            throw new IllegalArgumentException("Extent array must contain exactly four elements (leftLon, bottomLat, rightLon, topLat).");
        }
        double leftLon = extent[0];
        double bottomLat = extent[1];
        double rightLon = extent[2];
        double topLat = extent[3];
        // 将瓦片坐标转换回经度和纬度
        double tileLon = getLongitudeFromOSMTileX(x, zoom);
        double tileLat = getLatitudeFromOSMTileY(y, zoom);
        // 检查瓦片中心点的经纬度是否在给定范围内
        return (tileLon >= leftLon && tileLon <= rightLon) && (tileLat >= bottomLat && tileLat <= topLat);
    }

    /**
     * 计算下载量
     * @param bytes 图块x坐标
     * @return 下载量大小 B KN KB GB
     */
    public static String convertBytesToAppropriateUnit(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return String.format("%.2f KB", bytes / 1024.0);
        } else if (bytes < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", bytes / (1024.0 * 1024));
        } else {
            return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
        }
    }

    public static void main(String[] args) {
        int zoomLevel = 17;
        double[] extent = {117.421875, 38.82259097617712, 118.125, 39.36827914916013};
        int xExample = 108103;
        int yExample = 50053;

        if (isTileInExtent(xExample, yExample, zoomLevel, extent)) {
            System.out.println("Tile at x=" + xExample + ", y=" + yExample + " is within the specified extent.");
        } else {
            System.out.println("Tile at x=" + xExample + ", y=" + yExample + " is outside the specified extent.");
        }
        /*System.out.println(getOSMTileXFromLongitude(-180, 5));
        System.out.println(getOSMTileXFromLongitude(180, 5));
        System.out.println(getOSMTileYFromLatitude(-90, 5));
        System.out.println(getOSMTileYFromLatitude(90, 5));*/

    }

}
